package com.trt.beibei.service;

import com.github.wxpay.sdk.LinWxPayConfig;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.trt.beibei.core.LocalUser;
import com.trt.beibei.exception.http.ForbiddenException;
import com.trt.beibei.exception.http.NotFoundException;
import com.trt.beibei.exception.http.ParameterException;
import com.trt.beibei.exception.http.ServerErrorException;
import com.trt.beibei.model.Order;
import com.trt.beibei.repository.OrderRepository;
import com.trt.beibei.util.CommonUtil;
import com.trt.beibei.util.HttpRequestProxy;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * @author tanrentao
 * @date 2021-08-17
 * @desc
 */
@Service
public class WxPaymentService {

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private OrderService orderService;

    @Value("${beibei.order.pay-callback-host}")
    private String payCallbackHost;

    @Value("${beibei.order.pay-callback-path}")
    private String payCallbackPath;

    private static LinWxPayConfig linWxPayConfig = new LinWxPayConfig(); // 配置文件初始化的参数

    public Map<String, String> preOrder(Long oid) {
        Long uid = LocalUser.getUser().getId();
        Optional<Order> optionalOrder = orderRepository.findFirstByUserIdAndId(uid, oid);
        Order order = optionalOrder.orElseThrow(
                () -> new NotFoundException(50009));
        if (order.needCancel()) {
            throw new ForbiddenException(50010);
        }
        WXPay wxPay = assembleWxPayConfig();
        Map<String, String> params = makePreOrderParams(order.getFinalTotalPrice(), order.getOrderNo());
        Map<String, String> wxOrder;
        try {
            // 统一下单
            wxOrder = wxPay.unifiedOrder(params);
        } catch (Exception e) {
            throw new ServerErrorException(9999);
        }
        // prepay_id 微信服务器订单号
        // wx.requestPayment
        if (unifiedOrderSuccess(wxOrder)) {
            orderService.updateOrderPrepayId(order.getId(), wxOrder.get("prepay_id")); // 将微信服务器订单号 更新到本系统
        }
        return makePaySignature(wxOrder);
    }

    // WXPay真正传向微信服务器配置参数
    public WXPay assembleWxPayConfig() {
        WXPay wxPay;
        try {
            wxPay = new WXPay(linWxPayConfig);
        } catch (Exception ex) {
            throw new ServerErrorException(9999);
        }
        return wxPay;
    }

    // 配置订单信息
    private Map<String, String> makePreOrderParams(BigDecimal serverFinalPrice, String orderNo) {
        String payCallbackUrl = payCallbackHost + payCallbackPath;
        Map<String, String> data = new HashMap<>();
        data.put("body", "Sleeve");  // 商品标题，自定义
        data.put("out_trade_no", orderNo);// 订单号
        data.put("device_info", "Sleeve");
        data.put("fee_type", "CNY");
        data.put("trade_type", "JSAPI");

        data.put("total_fee", CommonUtil.yuanToFenPlainString(serverFinalPrice));
        data.put("openid", LocalUser.getUser().getOpenid());
        data.put("spbill_create_ip", HttpRequestProxy.getRemoteRealIp());

        data.put("notify_url", payCallbackUrl);
        return data;
    }

    // 统一下单是否成功
    private boolean unifiedOrderSuccess(Map<String, String> wxOrder) {
        if (!wxOrder.get("return_code").equals("SUCCESS")
                || !wxOrder.get("result_code").equals("SUCCESS")) {
            throw new ParameterException(10007);
        }
        return true;
    }


    // 定义返回小程序的参数
    private Map<String, String> makePaySignature(Map<String, String> wxOrder) {
        Map<String, String> wxPayMap = new HashMap<>();
        String packages = "prepay_id=" + wxOrder.get("prepay_id");

        wxPayMap.put("appId", linWxPayConfig.getAppID());

        wxPayMap.put("timeStamp", CommonUtil.timestamp10()); // 10时间戳  严格13位
        wxPayMap.put("nonceStr", RandomStringUtils.randomAlphanumeric(32));
        wxPayMap.put("package", packages);
        wxPayMap.put("signType", "HMAC-SHA256");

        String sign;
        try {
            // 微信支付签名计算
            sign = WXPayUtil.generateSignature(wxPayMap, linWxPayConfig.getKey(), WXPayConstants.SignType.HMACSHA256);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServerErrorException(9999);
        }

        // 返回小程序的参数
        Map<String, String> miniPayParams = new HashMap<>();

        miniPayParams.put("paySign", sign);
        miniPayParams.putAll(wxPayMap);
        miniPayParams.remove("appId");
        return miniPayParams;
    }







}
